/**
 * 重构对比：Entity 属性 vs Component 数据
 * 
 * 展示重构前后的代码对比，以及各自的优缺点
 */

import { ecs } from "../../../../core/ecs/ECS";
import { Player } from "./player";  // 旧版
import { PlayerRefactored } from "./player_refactored";  // 新版

export class RefactoringComparison {
    /**
     * 示例 1：创建和使用对比
     */
    static example1_BasicUsage(): void {
        console.log('=== 示例 1：基础使用对比 ===\n');
        
        // ❌ 旧版：属性直接在 Entity 中
        console.log('--- 旧版（属性在 Entity） ---');
        const oldPlayer = ecs.getEntity(Player);
        oldPlayer.currentHealth -= 30;
        oldPlayer.level++;
        oldPlayer.score += 100;
        console.log(`HP: ${oldPlayer.currentHealth}, Level: ${oldPlayer.level}, Score: ${oldPlayer.score}`);
        
        // ✅ 新版：数据在 Component 中
        console.log('\n--- 新版（数据在 Component） ---');
        const newPlayer = ecs.getEntity(PlayerRefactored);
        newPlayer.HealthComponent.takeDamage(30);
        newPlayer.LevelComponent.levelUp();
        newPlayer.ScoreComponent.add(100);
        console.log(`HP: ${newPlayer.HealthComponent.current}, Level: ${newPlayer.LevelComponent.level}, Score: ${newPlayer.ScoreComponent.value}`);
        
        // 或者使用便捷方法
        console.log('\n--- 新版（使用便捷方法） ---');
        newPlayer.takeDamage(30);
        newPlayer.addScore(100);
        console.log(newPlayer.getSummary());
    }
    
    /**
     * 示例 2：组件复用
     */
    static example2_ComponentReuse(): void {
        console.log('\n=== 示例 2：组件复用 ===\n');
        
        // ❌ 旧版：无法复用，Enemy 需要重复定义 health
        console.log('--- 旧版：代码重复 ---');
        console.log(`
@ecs.register('Enemy')
class Enemy extends ecs.Entity {
    // ❌ 重复代码！和 Player 一样的 health 属性
    public maxHealth: number = 50;
    public currentHealth: number = 50;
}
        `);
        
        // ✅ 新版：组件可复用
        console.log('--- 新版：组件复用 ---');
        console.log(`
@ecs.register('Enemy')
class Enemy extends ecs.Entity {
    HealthComponent!: HealthComponent;  // ✅ 复用 Player 的组件！
    
    init() {
        this.add(HealthComponent);
        this.HealthComponent.set(50, 50);  // 敌人血量较少
    }
}

// Player 和 Enemy 共享同一个 HealthComponent 定义
// 代码量减少，维护更简单
        `);
    }
    
    /**
     * 示例 3：System 查询
     */
    static example3_SystemQuery(): void {
        console.log('\n=== 示例 3：System 查询 ===\n');
        
        // ❌ 旧版：难以统一处理
        console.log('--- 旧版：System 难以处理 ---');
        console.log(`
class DamageSystem extends ecs.System {
    damageAll(amount: number) {
        // ❌ 问题：Player 和 Enemy 的 health 访问方式不同
        // Player: player.currentHealth
        // Enemy: enemy.currentHealth
        // 无法统一处理！
        
        const players = ecs.query(Player);
        for (const p of players) {
            p.currentHealth -= amount;  // ← 直接访问属性
        }
        
        const enemies = ecs.query(Enemy);
        for (const e of enemies) {
            e.currentHealth -= amount;  // ← 重复代码
        }
    }
}
        `);
        
        // ✅ 新版：统一查询和处理
        console.log('--- 新版：System 统一处理 ---');
        console.log(`
class DamageSystem extends ecs.System {
    filter() {
        // ✅ 查询所有有 HealthComponent 的实体
        return ecs.allOf(HealthComponent);
    }
    
    damageAll(amount: number) {
        // ✅ 统一处理：Player, Enemy, NPC 等所有有生命的实体
        const entities = this.group.matchEntities;
        for (const entity of entities) {
            entity.HealthComponent.takeDamage(amount);  // ← 统一接口
        }
    }
}

// 一个方法处理所有实体，无需重复代码！
        `);
    }
    
    /**
     * 示例 4：代码量对比
     */
    static example4_CodeSize(): void {
        console.log('\n=== 示例 4：代码量对比 ===\n');
        
        console.log('假设有 Player, Enemy, NPC, Boss 四种实体都需要生命值：\n');
        
        console.log('--- 旧版：重复定义 ---');
        console.log(`
Player: 
  public maxHealth: number = 100;
  public currentHealth: number = 100;
  
Enemy:
  public maxHealth: number = 50;
  public currentHealth: number = 50;
  
NPC:
  public maxHealth: number = 30;
  public currentHealth: number = 30;
  
Boss:
  public maxHealth: number = 500;
  public currentHealth: number = 500;

总代码：4 × 2 行 = 8 行重复代码
维护成本：修改 health 逻辑需要改 4 个地方
        `);
        
        console.log('\n--- 新版：组件定义一次 ---');
        console.log(`
HealthComponent: (定义一次)
  public max: number = 100;
  public current: number = 100;
  takeDamage(amount: number) { /* ... */ }
  heal(amount: number) { /* ... */ }

Player, Enemy, NPC, Boss:
  HealthComponent!: HealthComponent;
  init() { this.add(HealthComponent); }

总代码：1 个组件定义 + 4 行使用
维护成本：修改 health 逻辑只需改 1 个地方 ✅
        `);
    }
    
    /**
     * 示例 5：访问路径对比
     */
    static example5_AccessPath(): void {
        console.log('\n=== 示例 5：访问路径对比 ===\n');
        
        const oldPlayer = ecs.getEntity(Player);
        const newPlayer = ecs.getEntity(PlayerRefactored);
        
        console.log('--- 旧版：访问路径短 ---');
        console.log(`player.currentHealth = 80;  // ✅ 简洁`);
        
        console.log('\n--- 新版：访问路径稍长 ---');
        console.log(`player.HealthComponent.current = 80;  // ⚠️ 稍显啰嗦`);
        
        console.log('\n--- 解决方案：添加便捷方法 ---');
        console.log(`
// 在 Entity 中添加便捷方法
class Player extends Entity {
    getHealth(): number {
        return this.HealthComponent.current;
    }
    
    setHealth(value: number): void {
        this.HealthComponent.current = value;
    }
}

// 使用
player.setHealth(80);  // ✅ 简洁且保持了组件化的优势
        `);
    }
    
    /**
     * 示例 6：性能对比
     */
    static example6_Performance(): void {
        console.log('\n=== 示例 6：性能对比 ===\n');
        
        const iterations = 10000;
        
        // 测试旧版
        console.log('测试中...');
        const oldStart = performance.now();
        for (let i = 0; i < iterations; i++) {
            const player = ecs.getEntity(Player);
            player.currentHealth -= 10;
            player.level++;
            player.score += 50;
            player.destroy();
        }
        const oldTime = performance.now() - oldStart;
        
        // 测试新版
        const newStart = performance.now();
        for (let i = 0; i < iterations; i++) {
            const player = ecs.getEntity(PlayerRefactored);
            player.HealthComponent.current -= 10;
            player.LevelComponent.level++;
            player.ScoreComponent.value += 50;
            player.destroy();
        }
        const newTime = performance.now() - newStart;
        
        console.log(`旧版（属性）: ${oldTime.toFixed(2)}ms`);
        console.log(`新版（组件）: ${newTime.toFixed(2)}ms`);
        console.log(`性能差异: ${((newTime - oldTime) / oldTime * 100).toFixed(1)}%`);
        console.log('\n结论：性能差异很小（< 10%），可以忽略');
    }
}

/**
 * 优缺点总结
 */
export const RefactoringSummary = {
    旧版_属性在Entity: {
        优点: [
            '访问路径短（player.health）',
            '代码简洁',
            '学习曲线平',
        ],
        缺点: [
            '❌ 代码重复（Player、Enemy 都要定义 health）',
            '❌ 难以复用',
            '❌ System 难以统一处理',
            '❌ 不符合 ECS 架构原则',
        ],
    },
    
    新版_数据在Component: {
        优点: [
            '✅ 组件可复用（减少重复代码）',
            '✅ System 可统一查询和处理',
            '✅ 数据组织清晰',
            '✅ 符合 ECS 架构原则',
            '✅ 易于扩展和维护',
        ],
        缺点: [
            '⚠️ 访问路径稍长（player.HealthComponent.current）',
            '⚠️ 学习曲线稍陡',
        ],
        解决方案: [
            '添加便捷方法（player.getHealth()）',
            '提供详细文档和示例',
        ],
    },
};

/**
 * 重构建议
 */
export const RefactoringRecommendation = `
应该将哪些数据重构为 Component？

✅ 应该组件化：
1. 通用数据（多个实体类型都需要）
   - health, position, velocity 等
   
2. 需要被 System 单独查询的数据
   - physics, ai, animation 等
   
3. 复杂的数据结构
   - inventory, skillTree, dialogue 等

⚠️ 可以保留在 Entity：
1. 实体唯一标识
   - entityId, playerId 等
   
2. 实体元数据
   - playerName, accountLevel 等
   
3. 临时标志
   - isInitialized, isDirty 等

你的 Player 实体：
- maxHealth/currentHealth → ✅ 应该组件化（HealthComponent）
- level → ✅ 应该组件化（LevelComponent）
- score → ✅ 应该组件化（ScoreComponent）

推荐：使用 PlayerRefactored 的实现方式！
`;

/**
 * 运行所有示例
 */
export function runRefactoringExamples(): void {
    console.log('╔════════════════════════════════════════╗');
    console.log('║   Entity 属性 vs Component 数据对比    ║');
    console.log('╚════════════════════════════════════════╝');
    
    RefactoringComparison.example1_BasicUsage();
    RefactoringComparison.example2_ComponentReuse();
    RefactoringComparison.example3_SystemQuery();
    RefactoringComparison.example4_CodeSize();
    RefactoringComparison.example5_AccessPath();
    RefactoringComparison.example6_Performance();
    
    console.log('\n' + '='.repeat(50));
    console.log(RefactoringRecommendation);
    console.log('='.repeat(50));
}

